/****************************************************************************
 *
 *  LinuxChatty
 *  Copyright (C) 2010, David Hsu.
 * 
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 ***************************************************************************/
#include "ResourceTable.h"
#include "xml/tinyxml.h"
#include <string>
#include <vector>

using namespace std;

/**
 * Constructor without loading a file.
 */
ResourceTable::ResourceTable():
	maxMenuTitleLength(0)
{
	// Nothing here
}

/**
 * Constructor with loading an initial resource XML file.
 * @param file Name of the XML file to load
 */
ResourceTable::ResourceTable(const char * file)
{
	LoadFile(file);
}

/**
 * Load the xml file specified and parse everything to the proper variables
 * @param file XML file that contains the program data
 */
bool ResourceTable::LoadFile(const char * file)
{
	maxMenuTitleLength = 0;
	menuList.clear();
	
	if (xmlDoc.LoadFile(file) == true)
	{
		TiXmlElement * root = xmlDoc.FirstChildElement();
		TiXmlElement * child = NULL;
		for (child = root->FirstChildElement();
		     child;
		     child = child->NextSiblingElement())
		{
			if ( strncmp(child->Value(), "App", 3) == 0 )
			{
			    // Title and version information
				TiXmlElement * item = NULL;
				for (item = child->FirstChildElement();
				     item;
				     item = item->NextSiblingElement())
				{
				    if ( strncmp(item->Value(), "Title", 5) == 0 )
				    {
				        appInfo.title = item->GetText();
				    }
				    else if ( strncmp(item->Value(), "Version", 7) == 0 )
				    {
				        appInfo.version = item->GetText();
				    }
				}
			}
			else if ( strncmp(child->Value(), "MainMenu", 8) == 0 )
			{
				// Loop through the main menu items and add the items to the
				// menu list.  While looping through the nodes, also count how
				// long the title is and keep track of the longest title.
				TiXmlElement * menu = NULL;
				for (menu = child->FirstChildElement();
				     menu;
				     menu = menu->NextSiblingElement())
				{
					if ( strncmp(menu->Value(), "Option", 7) == 0)
					{
						MenuItem mi;
						if (menu->QueryIntAttribute("key", &mi.key) != TIXML_SUCCESS) return false;
						mi.keyText = menu->Attribute("keytext");
						mi.data = menu->Attribute("data");
						mi.title = menu->Attribute("title");
						mi.desc = menu->Attribute("description");
						menuList.push_back(mi);
						
						if (mi.title.size() > maxMenuTitleLength)
							maxMenuTitleLength = mi.title.size();
					}
				}
			}
			else if ( strncmp(child->Value(), "ServerList", 10) == 0 )
			{
				// Loop through the list of servers
				TiXmlElement * server = NULL;
				for (server = child->FirstChildElement();
				     server;
				     server = server->NextSiblingElement())
				{
					if ( strncmp(server->Value(), "Server", 6) == 0)
					{
						RadioItem ri;
						int value;
						ri.name = server->Attribute("name");
						ri.url = server->Attribute("url");
						if (server->QueryIntAttribute("selected", &value) != TIXML_SUCCESS) return false;
						ri.selected = (value == 1);
						
						if (ri.name == "Custom")
							customServerURL = ri.url;
						if (ri.selected)
							selectedServer = ri.url;
						
						serverList.push_back(ri);
					}
				}
			}
			else if ( strncmp(child->Value(), "Authentication", 14) == 0 )
			{
				authentication = child->Attribute("code");
			}
		}
		
		return true;
	}
	return false;
}

/**
 * Saves the current settings using the same file that was loaded from before.
 */
bool ResourceTable::SaveFile()
{
	return xmlDoc.SaveFile();
}

/**
 * Accessor functions to get the title and version of the software.
 */
const std::string& ResourceTable::GetTitle() const
{
    return appInfo.title;
}

const std::string& ResourceTable::GetVersion() const
{
    return appInfo.version;
}
	
/**
 * Accessor function to return the menu list
 */
const vector<MenuItem>& ResourceTable::GetMenuList() const
{
	return menuList;
}

MenuItem ResourceTable::GetMenuListItem(unsigned int index)
{
	if (index >= 0 && index < menuList.size())
	{
		return menuList[index];
	}
	
	// If the index is out of bounds, return a blank structure
	return MenuItem();
}

unsigned int ResourceTable::NumMenuItems() const
{
	return menuList.size();
}

unsigned int ResourceTable::GetMaxMenuLength() const
{
	return maxMenuTitleLength;
}

const vector<RadioItem>& ResourceTable::GetServerList() const
{
	return serverList;
}

const string& ResourceTable::GetCustomServerURL() const
{
	return customServerURL;
}

const string& ResourceTable::GetSelectedServer() const
{
	return selectedServer;
}

const string& ResourceTable::GetAuthentication() const
{
	return authentication;
}

void ResourceTable::SetSelectedServer(const string& serverName)
{
	TiXmlElement * root = xmlDoc.FirstChildElement();
	TiXmlElement * child = NULL;
	for (child = root->FirstChildElement(); child; child = child->NextSiblingElement())
	{
		if ( strncmp(child->Value(), "ServerList", 10) == 0 )
		{
			// Loop through the list of servers and find the right server
			TiXmlElement * server = NULL;
			unsigned int i = 0;
			for (server = child->FirstChildElement(); server; 
				server = server->NextSiblingElement(), i++)
			{
				if ( strncmp(server->Value(), "Server", 6) == 0)
				{
					string name = server->Attribute("name");
					if (name == serverName)
					{
						server->SetAttribute("selected", 1);
						selectedServer = server->Attribute("url");
						serverList[i].selected = true;
					}
					else
					{
						server->SetAttribute("selected", 0);
						serverList[i].selected = false;
					}
				}
			}
			return;
		}
	}
}

void ResourceTable::SetCustomServerURL(const string& url)
{
	TiXmlElement * root = xmlDoc.FirstChildElement();
	TiXmlElement * child = NULL;
	for (child = root->FirstChildElement(); child; child = child->NextSiblingElement())
	{
		if ( strncmp(child->Value(), "ServerList", 10) == 0 )
		{
			// Loop through the list of servers and find the right server
			TiXmlElement * server = NULL;
			for (server = child->FirstChildElement(); server; server = server->NextSiblingElement())
			{
				if ( strncmp(server->Value(), "Server", 6) == 0)
				{
					string name = server->Attribute("name");
					if (name == "Custom")
					{
						server->SetAttribute("url", url.c_str());
						customServerURL = url;
						return;
					}
				}
			}
		}
	}
}

void ResourceTable::SetAuthorization(const string& auth)
{
	TiXmlElement * root = xmlDoc.FirstChildElement();
	TiXmlElement * child = NULL;
	for (child = root->FirstChildElement(); child; child = child->NextSiblingElement())
	{
		if ( strncmp(child->Value(), "Authentication", 14) == 0 )
		{
			child->SetAttribute("code", auth.c_str());
			authentication = auth;
			return;
		}
	}
}
